#include "filetable.h"
#include "fileoperations.h"
#include "randomdata.h"
#include <QVBoxLayout>
#include <QPushButton>
#include <QFileDialog>
#include "viewer.h"
#include <QAction>
#include <QMenu>


QStandardItemModel *FileTable::itemModel = 0;
QList<SLEPItem> *FileTable::slepItemList = 0;
QString *FileTable::currentDir = 0;
QString *FileTable::outputDir = 0;

void FileTable::initModel(){
	static bool done = false;
	if(!done){
		FileTable::currentDir = new QString(".");
		FileTable::outputDir = new QString(".");
		FileTable::itemModel = new QStandardItemModel(0,4);
		FileTable::slepItemList = new QList<SLEPItem>;
		FileTable::itemModel->setHeaderData(0, Qt::Horizontal, QObject::tr("Name"),Qt::EditRole);
		FileTable::itemModel->setHeaderData(1, Qt::Horizontal, QObject::tr("Type"),Qt::DisplayRole);
		FileTable::itemModel->setHeaderData(2, Qt::Horizontal, QObject::tr("Info"), Qt::EditRole );
		FileTable::itemModel->setHeaderData(3, Qt::Horizontal, QObject::tr("Full filename"),Qt::DisplayRole);
		done = true;
	}
}

FileTable::FileTable(QWidget *parent):QDialog(parent){

	FileTable::initModel();
    treeView = new QTreeView;
    treeView->setRootIsDecorated(false);
    treeView->setAlternatingRowColors(true);
    treeView->setModel(FileTable::itemModel);
    treeView->setSortingEnabled(false);
    treeView->setSelectionBehavior(QAbstractItemView::SelectRows);
    treeView->setSelectionMode(QAbstractItemView::SingleSelection);

    selection = new QItemSelectionModel(FileTable::itemModel);
    treeView->setSelectionModel(selection);

	actionAddMatrix = new QAction("Matrix(from file)", this);
	actionAddVector = new QAction("Vector(from file)", this);
	actionAddGroupIndices = new QAction("Group Info(from file)", this);
	actionAddRandomData = new QAction("New random data", this);
	actionViewData = new QAction("View Data", this);
	actionViewHistogram = new QAction("View Histogram", this);
	actionRemove = new QAction("Remove", this);
	actionAnyData = new QAction("File",this);

	actionChangeCurrentDir = new QAction("Change current directory",this);
	actionChangeOutputDir = new QAction("Change output directory",this);

	menuAdd = new QMenu("Add",this);
	menuView = new QMenu("View",this);
	menuMore = new QMenu("more...",this);

	menuAdd->addAction(actionAddMatrix);
	menuAdd->addAction(actionAddVector);
	menuAdd->addAction(actionAddRandomData);
	menuAdd->addAction(actionAddGroupIndices);
	menuAdd->addAction(actionAnyData);
	menuView->addAction(actionViewData);
	menuView->addAction(actionViewHistogram);
	menuMore->addAction(actionRemove);
	menuMore->addAction(actionChangeCurrentDir);
	menuMore->addAction(actionChangeOutputDir);

    QGridLayout *mainLayout = new QGridLayout;
    mainLayout->addWidget(treeView,0,0,1,6);
	toolButtonAdd = new QToolButton(this);
	toolButtonView = new QToolButton(this);
	toolButtonMore = new QToolButton(this);

	toolButtonAdd->setText("Add");
	toolButtonView->setText("View");
	toolButtonMore->setText("more...");

	toolButtonAdd->setMenu(menuAdd);
	toolButtonAdd->setPopupMode(QToolButton::InstantPopup);
	toolButtonAdd->setToolButtonStyle(Qt::ToolButtonTextOnly);
	toolButtonView->setMenu(menuView);
	toolButtonView->setPopupMode(QToolButton::InstantPopup);
	toolButtonView->setToolButtonStyle(Qt::ToolButtonTextOnly);
	toolButtonMore->setMenu(menuMore);
	toolButtonMore->setPopupMode(QToolButton::InstantPopup);
	toolButtonMore->setToolButtonStyle(Qt::ToolButtonTextOnly);
    mainLayout->addWidget(toolButtonAdd,1,0,1,1);
    mainLayout->addWidget(toolButtonView,1,1,1,1);
    mainLayout->addWidget(toolButtonMore,1,2,1,1);

    setLayout(mainLayout);
    connect(actionAddMatrix, SIGNAL(triggered()),this, SLOT(actAddMatrix()));
    connect(actionAddVector, SIGNAL(triggered()), this, SLOT(actAddVector()));
    connect(actionRemove, SIGNAL(triggered()), this, SLOT(actRemove()));
    connect(actionAddRandomData, SIGNAL(triggered()), this, SLOT(actAddRandomData()));
    connect(actionViewData, SIGNAL(triggered()), this, SLOT(actViewData()));
	connect(actionAddGroupIndices, SIGNAL(triggered()), this, SLOT(actAddGroupIndices()));
	connect(actionChangeCurrentDir, SIGNAL(triggered()), this, SLOT(actChangeCurrentDir()));
	connect(actionChangeOutputDir, SIGNAL(triggered()), this, SLOT(actChangeOutputDir()));
	connect(actionAnyData, SIGNAL(triggered()), this, SLOT(actAddSomething()));
	connect(selection,SIGNAL(selectionChanged(const QItemSelection &,const QItemSelection &)),this,SLOT(onSelectionChange(const QItemSelection &,const QItemSelection &)));
}

FileTable::~FileTable(){
}


QStandardItemModel* FileTable::getItemModel(){
    return FileTable::itemModel;
}

QList<SLEPItem>* FileTable::getSlepItemList(){
    return FileTable::slepItemList;
}

void FileTable::actAddMatrix(){
    int i;
    SLEPItem item;
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open matrix file"), tr("."), tr("All Formats (*.mat *.matb *.mtx *.mtb *.ijv *.ccs *.csc *.crs *.csr);;"
                                                                                                    "Matrix (*.mat);;"
                                                                                              "Matrix (binary storage) (*.matb *.mtx *.mtb);;"
                                                                                              "Sparse IJV Format (*.ijv);;"
                                                                                              "Sparse - Compressed Column Storage(*.ccs *.csc);;"
                                                                                              "Sparse - Compressed Row Storage(*.crs *.csr);;"
                                                                                              "All Files(*.*)"));


    for(i=0; i<fileNames.size(); i++){
        if( (QFileInfo(fileNames.at(i)).suffix().compare("mtx",Qt::CaseInsensitive)==0)
                    || (QFileInfo(fileNames.at(i)).suffix().compare("mtb",Qt::CaseInsensitive)==0)
                    || (QFileInfo(fileNames.at(i)).suffix().compare("matb",Qt::CaseInsensitive)==0) )
            item = FileOperations::readFile(fileNames.at(i));
        else
            item = FileOperations::readTextFile(fileNames.at(i));
        if(item.type != SLEPItem::NONE){
			FileTable::itemModel->insertRow(0);
            FileTable::slepItemList->insert(0,item);
            FileTable::itemModel->setData(FileTable::itemModel->index(0,0),QFileInfo(fileNames.at(i)).baseName());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,1),QString(SLEPItem::TYPES_LONG[FileTable::slepItemList->at(0).type]));
            FileTable::itemModel->setData(FileTable::itemModel->index(0,2),item.info());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,3),fileNames.at(i));
        }
    }
}



void FileTable::actAddVector(){
    int i;
    SLEPItem item;
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open vector"), tr("."), tr("All Formats (*.vec *.vct *.vctr *.vecb *.vcb *.vctb);;"
                                                                                                    "Vector (*.vec *.vct *.vctr);;"
                                                                                              "Vector (binary storage) (*.vecb *.vcb *.vctb);;"
                                                                                              "All Files(*.*)"));

    for(i=0; i<fileNames.size(); i++){
        if( (QFileInfo(fileNames.at(i)).suffix().compare("vctb",Qt::CaseInsensitive)==0)
                    ||	(QFileInfo(fileNames.at(i)).suffix().compare("vcb",Qt::CaseInsensitive)==0)
                    ||	(QFileInfo(fileNames.at(i)).suffix().compare("vecb",Qt::CaseInsensitive)==0))
            item = FileOperations::readFile(fileNames.at(i));
        else
            item = FileOperations::readTextFile(fileNames.at(i));
        if(item.type != SLEPItem::NONE){
            FileTable::itemModel->insertRow(0);
            FileTable::slepItemList->insert(0,item);
            FileTable::itemModel->setData(FileTable::itemModel->index(0,0),QFileInfo(fileNames.at(i)).baseName());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,1),QString(SLEPItem::TYPES_LONG[FileTable::slepItemList->at(0).type]));
            FileTable::itemModel->setData(FileTable::itemModel->index(0,2),item.info());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,3),fileNames.at(i));
        }
    }
}


void FileTable::actAddGroupIndices(){
    int i;
    SLEPItem item;
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open group information file"), tr("."), tr("Group indices (*.grp);;"));

    for(i=0; i<fileNames.size(); i++){
        if( (QFileInfo(fileNames.at(i)).suffix().compare("grp",Qt::CaseInsensitive)==0))
            item = FileOperations::readTextFile(fileNames.at(i));
        if(item.type != SLEPItem::NONE){
            FileTable::itemModel->insertRow(0);
            FileTable::slepItemList->insert(0,item);
            FileTable::itemModel->setData(FileTable::itemModel->index(0,0),QFileInfo(fileNames.at(i)).baseName());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,1),QString(SLEPItem::TYPES_LONG[FileTable::slepItemList->at(0).type]));
            FileTable::itemModel->setData(FileTable::itemModel->index(0,2),item.info());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,3),fileNames.at(i));
        }
    }
}

void FileTable::actRemove(){
    int i;

    if(selection->hasSelection()){
        for(i=0; i< itemModel->rowCount(); ++i)
            if(selection->isRowSelected(i,treeView->rootIndex())){
                FileTable::itemModel->removeRow(i);
                SLEPItem item = FileTable::slepItemList->at(i);
                item.dealloc();
                FileTable::slepItemList->removeAt(i);
            }
    }
}



void FileTable::actAddRandomData(){
    SLEPItem *item = new SLEPItem;
    QString saveFileAs;
    SLEPRandomDataWizard *randomDataWizard = new SLEPRandomDataWizard(*item, this);
    randomDataWizard->exec();
    if(item->type == SLEPItem::NONE)
        return;
    if(item->type== SLEPItem::DENSE_MATRIX || item->type== SLEPItem::SPARSE_MATRIX_CSC){
        saveFileAs = QFileDialog::getSaveFileName(this, tr("Save random matrix"), tr("."), tr("*.mtx"));
        FileOperations::writeFile(*item, saveFileAs);
    }else if(item->type== SLEPItem::DENSE_VECTOR || item->type== SLEPItem::SPARSE_VECTOR){
        saveFileAs = QFileDialog::getSaveFileName(this, tr("Save random vector"), tr("."), tr("*.vcb"));
        FileOperations::writeFile(*item, saveFileAs);
	}else if(item->type== SLEPItem::GROUP_INDICES){
        saveFileAs = QFileDialog::getSaveFileName(this, tr("Save random group information"), tr("."), tr("*.grp"));
        FileOperations::writeTextFile(*item, saveFileAs);
	}

    QFileInfo fileInfo(saveFileAs);

    FileTable::itemModel->insertRow(0);
    FileTable::slepItemList->insert(0,*item);
    FileTable::itemModel->setData(FileTable::itemModel->index(0,0),fileInfo.baseName());
    FileTable::itemModel->setData(FileTable::itemModel->index(0,1),QString(SLEPItem::TYPES_LONG[FileTable::slepItemList->at(0).type]));
    FileTable::itemModel->setData(FileTable::itemModel->index(0,2),item->info());
    FileTable::itemModel->setData(FileTable::itemModel->index(0,3),saveFileAs);

}


void FileTable::actViewData(){
    int i;

    if(selection->hasSelection()){
        for(i=0; i< FileTable::itemModel->rowCount(); ++i)
            if(selection->isRowSelected(i,treeView->rootIndex())){
                QString var = (FileTable::itemModel->data(FileTable::itemModel->index(i,0))).toString();
                selection->currentIndex().row();
                SLEPItem item = FileTable::slepItemList->at(i);
                if(item.type == SLEPItem::DENSE_MATRIX)
                    twoDViewer(item.data,item.m,item.n,var);
                else if(item.type == SLEPItem::DENSE_VECTOR)
                    oneDViewer(item.data,item.dimension,var);
                else return;
            }
    }
}



int FileTable::getSelection(){
    int i;
    if(selection->hasSelection()){
        for(i=0; i< FileTable::itemModel->rowCount(); ++i)
            if(selection->isRowSelected(i,treeView->rootIndex()))
                return i;
    }
    return -1;
}


int FileTable::getSelectionType(int selection){
    return (FileTable::slepItemList->at(selection)).type;
}

void FileTable::getDenseMatrix(int selection, int *m, int *n, double **data){
    *data = (FileTable::slepItemList->at(selection)).data;
    *m = (FileTable::slepItemList->at(selection)).m;
    *n = (FileTable::slepItemList->at(selection)).n;
}

void FileTable::getDenseVector(int selection, int *dimension, double **data){
	*data = (FileTable::slepItemList->at(selection)).data;
	*dimension = (FileTable::slepItemList->at(selection)).dimension;
}

void FileTable::getGroupIndices(int selection, int *size,int **indices){
	*indices = (FileTable::slepItemList->at(selection)).group_index;
	*size = (FileTable::slepItemList->at(selection)).group_size;
}



void FileTable::actChangeCurrentDir(){
	*FileTable::currentDir = QFileDialog::getExistingDirectory(this,"Select current directory",*FileTable::currentDir);
}


void FileTable::actChangeOutputDir(){
	*FileTable::outputDir = QFileDialog::getExistingDirectory(this,"Select output directory",*FileTable::outputDir);
}


void FileTable::actAddSomething(){
    int i;
    SLEPItem item;
    QStringList fileNames = QFileDialog::getOpenFileNames(this, tr("Open file"), tr("."), tr("All Formats (*.mat *.matb *.mtx *.mtb *.ijv *.ccs *.csc *.crs *.csr *.vec *.vct *.vctr *.vecb *.vcb *.vctb *.grp);;"
																							"Matrix All Formats (*.mat *.matb *.mtx *.mtb *.ijv *.ccs *.csc *.crs *.csr);;"
																							"Vector All Formats (*.vec *.vct *.vctr *.vecb *.vcb *.vctb);;"
																							"Group indices (*.grp);;"
                                                                                            "Matrix (*.mat);;"
                                                                                            "Matrix (binary storage) (*.matb *.mtx *.mtb);;"
                                                                                            "Sparse IJV Format (*.ijv);;"
                                                                                            "Sparse - Compressed Column Storage(*.ccs *.csc);;"
                                                                                            "Sparse - Compressed Row Storage(*.crs *.csr);;"
																								
                                                                                                "Vector (*.vec *.vct *.vctr);;"
                                                                                              "Vector (binary storage) (*.vecb *.vcb *.vctb);;"
                                                                                              "All Files(*.*)"));
    for(i=0; i<fileNames.size(); i++){
        if( (QFileInfo(fileNames.at(i)).suffix().compare("mtx",Qt::CaseInsensitive)==0)
                    || (QFileInfo(fileNames.at(i)).suffix().compare("mtb",Qt::CaseInsensitive)==0)
                    || (QFileInfo(fileNames.at(i)).suffix().compare("matb",Qt::CaseInsensitive)==0)
					||	(QFileInfo(fileNames.at(i)).suffix().compare("vctb",Qt::CaseInsensitive)==0)
                    ||	(QFileInfo(fileNames.at(i)).suffix().compare("vcb",Qt::CaseInsensitive)==0)
                    ||	(QFileInfo(fileNames.at(i)).suffix().compare("vecb",Qt::CaseInsensitive)==0))
            item = FileOperations::readFile(fileNames.at(i));
        else
            item = FileOperations::readTextFile(fileNames.at(i));
        if(item.type != SLEPItem::NONE){
			FileTable::itemModel->insertRow(0);
            FileTable::slepItemList->insert(0,item);
            FileTable::itemModel->setData(FileTable::itemModel->index(0,0),QFileInfo(fileNames.at(i)).baseName());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,1),QString(SLEPItem::TYPES_LONG[FileTable::slepItemList->at(0).type]));
            FileTable::itemModel->setData(FileTable::itemModel->index(0,2),item.info());
            FileTable::itemModel->setData(FileTable::itemModel->index(0,3),fileNames.at(i));
        }
    }
}


void FileTable::onSelectionChange(const QItemSelection &,const QItemSelection &){
    int i = -1;

    if(selection->hasSelection()){
		for(i=0; i< FileTable::itemModel->rowCount(); ++i)
            if(selection->isRowSelected(i,treeView->rootIndex()))
                break;
    }

    if(i!=-1)
		emit signalSelectionChanged((void*)(&(FileTable::slepItemList->at(i))) );

}